﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package blit {
    import Engine.Classes.*;
    import flash.display.*;
    import flash.geom.*;
    import Engine.Helpers.*;
    import Classes.*;
    import __AS3__.vec.*;
    import de.polygonal.ds.*;
    import com.zynga.skelly.render.*;

    public class BlitViewport extends IsoViewport implements IRenderer {

        public static const BACKGROUND:int = 0;
        public static const ROADS:int = 1;
        public static const BUILDINGS:int = 2;
        public static const ALPHAMASK:int = 3;
        public static const COMPOSITE:int = 4;
        public static const OUTPUT:int = 5;
        public static const NUMBUFFERS:int = 6;

        private var m_buffers:Vector.<BitmapData>;
        private var m_scratchAlphaBuffer:BitmapData;
        private var m_gameLayers:Vector.<GameObjectLayer>;
        private var m_blitViewportBitmap:Bitmap;
        private var m_setupBuffers:Boolean = true;
        private var m_alphaArray:Array;
        private var m_context:RenderContext;
        private var m_renderGrid:RenderGrid;
        private var m_tmpRectList:DLinkedList;
        private var once:Boolean = true;
        private var zeroPt:Point;

        public function BlitViewport(){
            this.m_buffers = new Vector.<BitmapData>(NUMBUFFERS);
            this.m_scratchAlphaBuffer = new BitmapData(0x0100, 0x0100, true, 0xFFFFFF);
            this.m_gameLayers = new Vector.<GameObjectLayer>(NUMBUFFERS);
            this.m_blitViewportBitmap = new Bitmap(null, PixelSnapping.NEVER);
            this.m_alphaArray = new Array(0x0100);
            this.m_context = new RenderContext();
            this.m_renderGrid = new RenderGrid();
            this.m_tmpRectList = new DLinkedList();
            this.zeroPt = new Point();
            super();
            this.m_alphaArray[0] = 4278190080;
            var _local1 = 1;
            while (_local1 < 0x0100) {
                this.m_alphaArray[_local1] = 0;
                _local1++;
            };
        }
        override public function addObjectLayer(_arg1:ObjectLayer):void{
            m_objectLayers.push(_arg1);
            m_objectLayers.sortOn("priority");
            if (_arg1.name == "road"){
                this.m_gameLayers[ROADS] = (_arg1 as GameObjectLayer);
            };
            if (_arg1.name == "default"){
                this.m_gameLayers[BUILDINGS] = (_arg1 as GameObjectLayer);
            };
        }
        override public function regenerateBitmapData():Boolean{
            var _local2:int;
            var _local1:Boolean;
            if ((((((m_bitmapData == null)) || (!((m_bitmapData.width == this.stage.width))))) || (!((m_bitmapData.height == this.stage.height))))){
                if (((((!((this.stage == null))) && ((this.stage.stageWidth > 0)))) && ((this.stage.stageHeight > 0)))){
                    if (m_bitmap.parent){
                        m_bitmap.parent.removeChild(m_bitmap);
                    };
                    if (m_bitmapData){
                        m_bitmapData.dispose();
                        m_bitmapData = null;
                    };
                    m_bitmapData = new BitmapData(this.stage.stageWidth, this.stage.stageHeight);
                    m_bitmap.bitmapData = m_bitmapData;
                    _local2 = 0;
                    while (_local2 < NUMBUFFERS) {
                        if (this.m_buffers[_local2]){
                            this.m_buffers[_local2].dispose();
                            this.m_buffers[_local2] = null;
                        };
                        _local2++;
                    };
                    this.m_buffers[BACKGROUND] = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, false);
                    this.m_buffers[ROADS] = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, true, 0xFFFFFF);
                    this.m_buffers[BUILDINGS] = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, true, 0xFFFFFF);
                    this.m_buffers[ALPHAMASK] = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, true, 0xFFFFFF);
                    this.m_buffers[COMPOSITE] = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, true, 0xFFFFFF);
                    this.m_buffers[OUTPUT] = new BitmapData(this.stage.stageWidth, this.stage.stageHeight, false);
                    this.initializeBackgroundData(this.m_buffers[BACKGROUND]);
                    if (this.m_blitViewportBitmap.parent){
                        this.m_blitViewportBitmap.parent.removeChild(this.m_blitViewportBitmap);
                    };
                    this.m_blitViewportBitmap.bitmapData = this.m_buffers[OUTPUT];
                    addChildAt(this.m_blitViewportBitmap, this.numChildren);
                    this.m_context.targetBuffer = this.m_buffers[OUTPUT];
                    this.m_context.backBuffer = this.m_buffers[COMPOSITE];
                    this.m_context.alphaBuffer = null;
                    _local1 = true;
                };
            };
            return (_local1);
        }
        override public function setScrollPosition(_arg1:Vector2):void{
            m_position = _arg1.cloneVec2();
            m_bitmapDirty = true;
        }
        private function initializeBackgroundData(_arg1:BitmapData):void{
            var _local2:Point = new Point((-(m_position.x) * 4), (-(m_position.y) * 4));
            _arg1.perlinNoise(150, 150, 1, 1, false, true, (2 | 4), false, [_local2]);
        }
        override protected function drawBackground(_arg1:BitmapData):void{
        }
        override protected function render(_arg1:Boolean=false):Boolean{
            var _local2:Boolean = super.render(_arg1);
            if (((_arg1) && (stage))){
                this.setupTransformMatrix();
                this.m_context.transformMatrix = m_absoluteTransformMatrix.clone();
                this.rebuildBuffers();
                _local2 = true;
            };
            return (_local2);
        }
        public function onRender(_arg1:int, _arg2:int):Boolean{
            if (((((Global.world) && (Global.hud))) && (this.once))){
                Global.world.updateWorld();
            };
            this.renderWorldToBuffer();
            return (true);
        }
        public function renderWorldToBuffer():void{
            if (!stage){
                return;
            };
            if (((m_bitmapData) && (m_bitmapDirty))){
                this.setupTransformMatrix();
                this.m_context.transformMatrix = m_absoluteTransformMatrix.clone();
                this.rebuildBuffers();
                m_bitmapDirty = false;
            };
            this.renderToBuffer();
        }
        protected function setupTransformMatrix():void{
            m_absoluteTransformMatrix.identity();
            m_absoluteTransformMatrix.translate(m_position.x, m_position.y);
            m_absoluteTransformMatrix.translate((-(this.stage.stageWidth) / 2), (-(this.stage.stageHeight) / 2));
            m_absoluteTransformMatrix.scale(m_zoom, m_zoom);
            m_absoluteTransformMatrix.translate((this.stage.stageWidth / 2), (this.stage.stageHeight / 2));
            objectBase.transform.matrix = (uiBase.transform.matrix = (overlayBase.transform.matrix = m_absoluteTransformMatrix));
        }
        protected function rebuildBuffers():void{
            this.initializeBackgroundData(this.m_buffers[BACKGROUND]);
            this.clearBuffersUsedForAlphaMask();
            this.renderLayersToBuffers();
            this.generateAlphaMaskBuffer();
            this.generateCompositeBuffer();
            this.copyCompositeBufferToOutput();
            this.m_gameLayers[ROADS].clearDirtyObjectList();
            this.m_gameLayers[BUILDINGS].clearDirtyObjectList();
        }
        protected function renderToBuffer():void{
            var _local3:Array;
            var _local4:int;
            var _local5:int;
            var _local6:Point;
            var _local7:DLinkedList;
            var _local8:DListNode;
            var _local9:NPC;
            var _local10:Rectangle;
            var _local11:Rectangle;
            this.m_context.transformMatrix = m_absoluteTransformMatrix.clone();
            this.m_tmpRectList.clear();
            if (((this.m_gameLayers[ROADS]) && (this.m_gameLayers[ROADS].dirty))){
                this.reRenderLayer(this.m_context, this.m_gameLayers[ROADS], this.m_buffers[ROADS]);
            };
            if (((this.m_gameLayers[BUILDINGS]) && (this.m_gameLayers[BUILDINGS].dirty))){
                this.reRenderLayer(this.m_context, this.m_gameLayers[BUILDINGS], this.m_buffers[BUILDINGS]);
            };
            this.reRenderAlphaMask(this.m_tmpRectList);
            this.reRenderCompositeLayer(this.m_tmpRectList);
            this.reRenderCompositeToOutput(this.m_tmpRectList);
            this.m_tmpRectList.clear();
            this.m_context.targetBuffer = this.m_buffers[OUTPUT];
            this.m_context.alphaBuffer = this.m_buffers[ALPHAMASK];
            this.m_context.backBuffer = this.m_buffers[COMPOSITE];
            this.m_context.targetBuffer.lock();
            this.m_renderGrid.clearGrid();
            var _local1:int;
            while (_local1 < m_objectLayers.length) {
                if (m_objectLayers[_local1].name == "npc"){
                    _local3 = m_objectLayers[_local1].children;
                    _local4 = _local3.length;
                    _local5 = 0;
                    while (_local5 < _local4) {
                        _local9 = (_local3[_local5] as NPC);
                        if (_local9){
                            _local10 = _local9.calcDirtyRect(this.m_context);
                            this.m_renderGrid.addDirtyRect(_local10);
                        };
                        _local5++;
                    };
                    _local6 = new Point();
                    _local7 = this.m_renderGrid.dirtyRects;
                    _local8 = _local7.head;
                    while (_local8) {
                        _local11 = _local8.data;
                        _local11.x = int(_local11.x);
                        _local11.y = int(_local11.y);
                        _local6.x = _local11.x;
                        _local6.y = _local11.y;
                        this.m_context.targetBuffer.copyPixels(this.m_context.backBuffer, _local11, _local6);
                        _local8 = _local8.next;
                    };
                    _local5 = 0;
                    while (_local5 < _local4) {
                        _local3[_local5].render(this.m_context);
                        _local5++;
                    };
                };
                _local1++;
            };
            this.m_context.targetBuffer.unlock();
            var _local2:int;
            while (_local2 < this.m_gameLayers.length) {
                if (this.m_gameLayers[_local2]){
                    this.m_gameLayers[_local2].postRender();
                };
                _local2++;
            };
        }
        protected function clearBuffersUsedForAlphaMask():void{
            this.m_buffers[ROADS].fillRect(this.m_buffers[ROADS].rect, 0xFFFFFF);
            this.m_buffers[BUILDINGS].fillRect(this.m_buffers[BUILDINGS].rect, 0xFFFFFF);
            this.m_buffers[ALPHAMASK].fillRect(this.m_buffers[ALPHAMASK].rect, 0xFFFFFF);
        }
        protected function renderLayersToBuffers():void{
            var _local3:Array;
            var _local4:int;
            var _local5:int;
            var _local1:Point = new Point();
            var _local2:int;
            while (_local2 < NUMBUFFERS) {
                if (this.m_gameLayers[_local2]){
                    this.m_context.targetBuffer = this.m_buffers[_local2];
                    this.m_context.alphaBuffer = null;
                    _local3 = this.m_gameLayers[_local2].children;
                    _local4 = _local3.length;
                    _local5 = 0;
                    while (_local5 < _local4) {
                        _local3[_local5].render(this.m_context);
                        _local5++;
                    };
                };
                _local2++;
            };
        }
        protected function generateAlphaMaskBuffer():void{
            var _local1:Point = new Point();
            this.m_buffers[ALPHAMASK].copyPixels(this.m_buffers[BUILDINGS], this.m_buffers[BUILDINGS].rect, _local1, this.m_buffers[ROADS], _local1, false);
            this.m_buffers[ALPHAMASK].paletteMap(this.m_buffers[ALPHAMASK], this.m_buffers[ALPHAMASK].rect, _local1, null, null, null, this.m_alphaArray);
        }
        protected function generateCompositeBuffer():void{
            var _local1:Point = new Point();
            this.m_buffers[COMPOSITE].copyPixels(this.m_buffers[BACKGROUND], this.m_buffers[BACKGROUND].rect, _local1);
            this.m_buffers[COMPOSITE].copyPixels(this.m_buffers[ROADS], this.m_buffers[ROADS].rect, _local1, null, null, true);
            this.m_buffers[COMPOSITE].copyPixels(this.m_buffers[BUILDINGS], this.m_buffers[BUILDINGS].rect, _local1, null, null, true);
        }
        protected function copyCompositeBufferToOutput():void{
            var _local1:Point = new Point();
            this.m_buffers[OUTPUT].copyPixels(this.m_buffers[COMPOSITE], this.m_buffers[COMPOSITE].rect, _local1);
        }
        protected function reRenderLayer(_arg1:RenderContext, _arg2:GameObjectLayer, _arg3:BitmapData):void{
            var _local5:Rectangle;
            var _local6:MapResource;
            var _local4:DLinkedList = _arg2.dirtyObjectList;
            var _local7:DListNode = _local4.head;
            while (_local7) {
                _local6 = (_local7.data as MapResource);
                if (_local6){
                    _local5 = _local6.calcDirtyRectMapResource(_arg1);
                    this.m_tmpRectList.append(_local5);
                    _arg3.fillRect(_local5, 0xFFFFFF);
                };
                _local7 = _local7.next;
            };
            this.renderLayerToBuffer(_arg2, _arg3);
            _local7 = _local4.head;
            while (_local7) {
                _local6 = (_local7.data as MapResource);
                if (_local6){
                    _local5 = _local6.calcDirtyRectMapResource(_arg1);
                    this.m_tmpRectList.append(_local5);
                };
                _local7 = _local7.next;
            };
            _arg2.clearDirtyObjectList();
        }
        protected function renderLayerToBuffer(_arg1:GameObjectLayer, _arg2:BitmapData):void{
            this.m_context.targetBuffer = _arg2;
            this.m_context.alphaBuffer = null;
            var _local3:Array = _arg1.children;
            var _local4:int = _local3.length;
            var _local5:int;
            while (_local5 < _local4) {
                _local3[_local5].render(this.m_context);
                _local5++;
            };
        }
        protected function reRenderAlphaMask(_arg1:DLinkedList):void{
            var _local2:Point;
            var _local3:Rectangle;
            var _local4:Point;
            var _local5:Rectangle;
            var _local6:DListNode;
            if (_arg1.size){
                _local2 = new Point();
                _local4 = new Point();
                _local5 = new Rectangle();
                _local6 = _arg1.head;
                while (_local6) {
                    _local3 = _local6.data;
                    _local3.x = int(_local3.x);
                    _local3.y = int(_local3.y);
                    _local2.x = _local3.x;
                    _local2.y = _local3.y;
                    _local5.width = _local3.width;
                    _local5.height = _local3.height;
                    this.m_scratchAlphaBuffer.fillRect(_local5, 4294967295);
                    this.m_scratchAlphaBuffer.copyPixels(this.m_buffers[BUILDINGS], _local3, _local4, this.m_buffers[ROADS], _local2, false);
                    this.m_scratchAlphaBuffer.paletteMap(this.m_scratchAlphaBuffer, _local5, _local4, null, null, null, this.m_alphaArray);
                    this.m_buffers[ALPHAMASK].copyPixels(this.m_scratchAlphaBuffer, _local5, _local2);
                    _local6 = _local6.next;
                };
            };
        }
        protected function reRenderCompositeLayer(_arg1:DLinkedList):void{
            var _local2:Point;
            var _local3:Rectangle;
            var _local4:DListNode;
            if (_arg1.size){
                _local2 = new Point();
                _local4 = _arg1.head;
                while (_local4) {
                    _local3 = _local4.data;
                    _local3.x = int(_local3.x);
                    _local3.y = int(_local3.y);
                    _local2.x = _local3.x;
                    _local2.y = _local3.y;
                    this.m_buffers[COMPOSITE].copyPixels(this.m_buffers[BACKGROUND], _local3, _local2);
                    this.m_buffers[COMPOSITE].copyPixels(this.m_buffers[ROADS], _local3, _local2, null, null, true);
                    this.m_buffers[COMPOSITE].copyPixels(this.m_buffers[BUILDINGS], _local3, _local2, null, null, true);
                    _local4 = _local4.next;
                };
            };
        }
        protected function reRenderCompositeToOutput(_arg1:DLinkedList):void{
            var _local2:Point;
            var _local3:Rectangle;
            var _local4:DListNode;
            if (_arg1.size){
                _local2 = new Point();
                _local4 = _arg1.head;
                while (_local4) {
                    _local3 = _local4.data;
                    _local3.x = int(_local3.x);
                    _local3.y = int(_local3.y);
                    _local2.x = _local3.x;
                    _local2.y = _local3.y;
                    this.m_buffers[OUTPUT].copyPixels(this.m_buffers[COMPOSITE], _local3, _local2);
                    _local4 = _local4.next;
                };
            };
        }
        protected function iterateDisplayList(_arg1:DisplayObjectContainer, _arg2:String):void{
            var _local3:int;
            var _local4:DisplayObject;
            while (_local3 < _arg1.numChildren) {
                _local4 = _arg1.getChildAt(_local3);
                if (_local4){
                };
                _arg2 = (_arg2 + " ");
                if (((_local4) && ((_local4 is DisplayObjectContainer)))){
                    this.iterateDisplayList((_local4 as DisplayObjectContainer), _arg2);
                };
                _local3++;
            };
        }

    }
}//package blit 
